package com.wgo.precise.server.pdf;

import java.util.HashSet;
import java.util.Set;

import org.apache.log4j.Logger;
import org.hibernate.exception.ExceptionUtils;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.wgo.bpot.server.persist.PersistService;

public class PdfFactoryRegistry {
	private static final Logger log = Logger.getLogger(PdfFactoryRegistry.class);
	
	private Set<PdfFactory> factories = new HashSet<PdfFactory>();
	private PersistService persistService;
	
	

	public PersistService getPersistService() {
		return persistService;
	}

	public void setPersistService(PersistService persistService) {
		this.persistService = persistService;
	}

	public void addFactory(PdfFactory factory){
		factory.setRegistry(this);
		factories.add(factory);
	}
	
	public void initFactories(){
		for (PdfFactory factory : factories) {
			factory.setRegistry(this);
		}
	}

	public void writeDocument(Document doc,String conceptType, Long id){
		PdfFactory factory = getElementFactory(conceptType);
		if (null != factory) {
			Object concept = loadConcept(factory.getConceptClass(),id);
			if (null != concept) {
				writeDocument(doc,concept,factory,0);
			} else {
				log.warn("Unable to load concept " + factory.getConceptClass().getSimpleName() + " with id=" + id);
			}
		} else {
			log.warn("Unable to locate factory to handle concept type:" + conceptType);
		}
	}
	
	public void writeDocument(Document doc,Object concept){
		writeDocument(doc,concept,0);
	}
	
	public void writeDocument(Document doc,Object concept, int indentation){
		PdfFactory factory = getElementFactory(concept);
		writeDocument(doc,concept,factory,indentation);
	}
	
	private void writeDocument(Document doc, Object concept, PdfFactory factory, int indentation) {
		if (null == factory) {
			log.warn("Unable to locate element factory for concept type " + factory.getType());
		} else {
			try {
				factory.writeElement(concept,doc,indentation);
			} catch (DocumentException e) {
				log.error("Failed creating document using concept " + factory.getType() + ".\n" + ExceptionUtils.getFullStackTrace(e));
			}
		}		
	}

	private PdfFactory getElementFactory(Object concept) {
		for (PdfFactory factory : factories) {
			if (factory.getConceptClass().isInstance(concept)) {
				return factory;
			}
		}
		return null;
	}

	public void writeDocument(Document doc,String conceptType, String idStr){
		if ((null != doc) && (null != conceptType) && (null != idStr)) {
			Long id = Long.parseLong(idStr);
			writeDocument(doc,conceptType,id);
		} else {
			log.warn("Unable to process request to create PDF due to missing information. Ensure the component type and id is passed as request arguments.");
		}
	}
	
	private PdfFactory getElementFactory(String conceptType){
		for (PdfFactory factory : factories) {
			if (factory.getType().equals(conceptType)) {
				return factory;
			}
		}
		return null;
	}
	
	@SuppressWarnings("unchecked")
	private Object loadConcept(Class domainClass, Long id) {		
		Object result = null;
//		Class ejbClass = persistService.getDomainModelConvention().apiToEjb(domainClass);
//		if (null == ejbClass) {
//			log.error("Unable to locate mapped Ejb for class " + domainClass);
//		} else {
			result = persistService.getDbInstance(domainClass,id);
			if (null == result) {
				log.error("Unable to locate persisted instanse of type " + domainClass.getSimpleName() + " with id " + id);
//			}
		}
		return result;
	}
	

}
